package com.ruoyi.business.youdaoController;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.business.services.HttpService;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.enums.SaveType;
import com.ruoyi.common.utils.EncrypDES;
import com.ruoyi.common.utils.GetUrlParam;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.system.domain.vo.R;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;

@RestController
@RequestMapping("ownTxToMmApi")
public class TengXunToMomoApiController {

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private HttpService httpService;

    private final static String CLASSESEN = "youdao";




    @Log(title = "有道", businessType = BusinessType.ESCALATION, esIndex = "youdao_log", saveType = SaveType.ES)
    @RequestMapping("/send")
    public Object send(HttpServletRequest request) throws Exception {
        String queryString = request.getQueryString();
        String channelId = request.getParameter("channelId");
        String dmpid = request.getParameter("dmpid");
        if(StringUtils.isBlank(channelId) || "null".equals(channelId)){
            return R.failure().msg("channelId不能为空");
        }
        if(StringUtils.isBlank(dmpid) || "null".equals(dmpid)){
            return R.failure().msg("dmpid不能为空");
        }

        Map<String, Object> baseParamsMap = GetUrlParam.queryStrToMap(queryString);

        baseParamsMap.remove("channelId");
        baseParamsMap.remove("dmpid");


        Map<String, Object> channelDetail = redisCache.getCacheMapValue(CLASSESEN+"Cache", channelId);
        if(channelDetail == null){
            return R.failure().msg("channelId不正确");
        }
        String url = channelDetail.get("request_address") + "";
        String requestType = channelDetail.get("request_type") + "";
        String requestAddress = GetUrlParam.getRequestAddress(url);
        String staticParameters = GetUrlParam.TruncateUrlPage(url);
        Map<String, Object> staticParamsMap = GetUrlParam.queryStrToMap(staticParameters);
        baseParamsMap.putAll(staticParamsMap);


        String ua = baseParamsMap.get("ua") + "";
        String ip = baseParamsMap.get("ip") + "";
        if(StringUtils.isNotBlank(ua) && !"null".equals(ua)){
            ua = URLDecoder.decode(ua, Constants.UTF8);
        }else{
            //request 获取 ua
//            ua = request.getHeader("User-Agent");
//            baseParamsMap.put("ua", URLEncoder.encode(ua, Constants.UTF8));
        }
        if(StringUtils.isNotBlank(ip) && !"null".equals(ip)){
        }else{
            //request 获取 ip
//            ip = IpUtils.getIpAddr(request);
        }



        String callbackUrl = URLDecoder.decode(baseParamsMap.get("callback") + "", Constants.UTF8);
        String callbackRequestAddress = GetUrlParam.getRequestAddress(callbackUrl);
        String callbackStaticParameters = GetUrlParam.TruncateUrlPage(callbackUrl);
        EncrypDES encrypDES = new EncrypDES();
//        String callbackBase = OtherUtils.getServerUrl(request) + "ownCommonApi/callback/"+ channelId +"/"+ dmpid +"/";
        String callbackBase = "https://www.ssptqt.com/ownTxToMmApi/callback/"+ channelId +"/"+ dmpid +"/";
        String encrypt_u = encrypDES.encrypt(callbackRequestAddress);

        // 构建回调URL，将腾讯转化归因需要的参数拼接到URL后面
        StringBuilder callbackParams = new StringBuilder();
        if (StringUtils.isNotBlank(callbackStaticParameters)) {
            callbackParams.append(callbackStaticParameters);
        }

        // 添加腾讯转化归因需要的设备标识参数
        String imei = getMapValue(baseParamsMap, "imei");
        String idfa = getMapValue(baseParamsMap, "idfa");
        String caid = getMapValue(baseParamsMap, "caid");
        String androididMd5 = getMapValue(baseParamsMap, "androidid_md5");
        String oaid = getMapValue(baseParamsMap, "oaid");
        String oaidMd5 = getMapValue(baseParamsMap, "oaid_md5");


        String os = getMapValue(baseParamsMap, "os");

        if (StringUtils.isNotBlank(imei)) {
            if (callbackParams.length() > 0) callbackParams.append("&");
            callbackParams.append("tencent_imei=").append(URLEncoder.encode(imei, Constants.UTF8));
        }
        if (StringUtils.isNotBlank(idfa)) {
            if (callbackParams.length() > 0) callbackParams.append("&");
            callbackParams.append("tencent_idfa=").append(URLEncoder.encode(idfa, Constants.UTF8));
        }
        if (StringUtils.isNotBlank(caid)) {
            if (callbackParams.length() > 0) callbackParams.append("&");
            callbackParams.append("tencent_caid=").append(URLEncoder.encode(caid, Constants.UTF8));
        }
        if (StringUtils.isNotBlank(os)) {
            if (callbackParams.length() > 0) callbackParams.append("&");
            callbackParams.append("tencent_os=").append(URLEncoder.encode(os, Constants.UTF8));
        }
        if (StringUtils.isNotBlank(androididMd5)) {
            if (callbackParams.length() > 0) callbackParams.append("&");
            callbackParams.append("tencent_androididMd5=").append(URLEncoder.encode(androididMd5, Constants.UTF8));
        }
        if (StringUtils.isNotBlank(oaid)) {
            if (callbackParams.length() > 0) callbackParams.append("&");
            callbackParams.append("tencent_oaid=").append(URLEncoder.encode(oaid, Constants.UTF8));
        }
        if (StringUtils.isNotBlank(oaidMd5)) {
            if (callbackParams.length() > 0) callbackParams.append("&");
            callbackParams.append("tencent_oaidMd5=").append(URLEncoder.encode(oaidMd5, Constants.UTF8));
        }
                

        String nu = callbackBase + encrypt_u + "?" + callbackParams.toString();
//        //nu必须是https请求
//        nu = nu.replace("http://", "https://");
        //抖音回调地址取得参数是callback
        baseParamsMap.put("callback", URLEncoder.encode(nu, Constants.UTF8));

        List<String> tempList = new ArrayList<>();
        for(String key: baseParamsMap.keySet()){
            tempList.add(key+"="+baseParamsMap.get(key));
        }
        String requestParameters = String.join("&", tempList);


        String uuid = IdUtils.fastSimpleUUID();
        String reqType = "click";

        if("POST".equals(requestType)){
            httpService.sendPost(requestAddress, requestParameters, ip, ua, uuid, reqType);
        }else{
            httpService.sendGet(requestAddress, requestParameters, ip, ua, uuid, reqType);
        }
        return R.success().msg(uuid);
    }



    @Log(title = "有道", businessType = BusinessType.CALLBACK, esIndex = "youdao_log", saveType = SaveType.ES)
    @RequestMapping("/callback/{channelId}/{dmpid}/{encryptedUrl}")
    public Object callback(HttpServletRequest request, @PathVariable("channelId") String channelId,
                          @PathVariable("dmpid") String dmpid, @PathVariable("encryptedUrl") String encryptedUrl) throws Exception {
        String queryString = request.getQueryString();
        EncrypDES encrypDES = new EncrypDES();
        String requestAddress = encrypDES.decrypt(encryptedUrl);

        // 先执行原有的callback逻辑
        String uuid = IdUtils.fastSimpleUUID();
        String reqType = "callback";
        httpService.sendGet(requestAddress, queryString, null, null, uuid, reqType);

        sendTencentConversionApi(reqType, uuid, requestAddress, queryString, dmpid);

        return R.success().msg(uuid);
    }

    private String getMapValue(Map<String, Object> map, String key){
        if(map == null){
            return "";
        }
        if(map.get(key) == null){
            return "";
        }
        return map.get(key)+"";
    }

    /**
     * 发送腾讯转化归因API请求
     * @param requestAddress 请求地址
     * @param callbackQueryString callback的查询参数
     * @param dmpid 用于生成outer_action_id
     */
    private void sendTencentConversionApi(String reqType, String uuid, String requestAddress, String callbackQueryString, String dmpid) {
        try {
            Map<String, Object> callbackParams = GetUrlParam.queryStrToMap(callbackQueryString);
            String tencentImei = getMapValue(callbackParams, "tencent_imei");
            String tencentIdfa = getMapValue(callbackParams, "tencent_idfa");
            String tencentCaid = getMapValue(callbackParams, "tencent_caid");
            String tencentOs = getMapValue(callbackParams, "tencent_os");
            String tencentAndroididMd5 = getMapValue(callbackParams, "tencent_androididMd5");
            String tencentOaid = getMapValue(callbackParams, "tencent_oaid");
            String tencentOaidMd5 = getMapValue(callbackParams, "tencent_oaidMd5");
            String event = getMapValue(callbackParams, "event");

            // 构建请求体
            JSONObject requestBody = buildTencentRequestBody(tencentImei, tencentIdfa, tencentCaid, tencentOs, 
            tencentAndroididMd5, tencentOaid, tencentOaidMd5, dmpid, event);

            // 构建请求头
            Map<String, String> headers = new HashMap<>();
            headers.put("Content-Type", "application/json");
//            headers.put("access-token", "<ACCESS_TOKEN>"); // 需要配置实际的access token
//            headers.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
//            headers.put("nonce", IdUtils.fastSimpleUUID());
//            headers.put("cache-control", "no-cache");


            String cb = getMapValue(callbackParams, "cb");
            String convId = getMapValue(callbackParams, "conv_id");
            requestAddress = requestAddress + "?cb=" + cb + "&conv_id=" + convId;

            // 发送请求
            httpService.sendPost(requestAddress, requestBody.toJSONString(), headers, uuid, reqType);

            System.out.println("腾讯转化归因API请求已发送: " + requestAddress);

        } catch (Exception e) {
            System.err.println("发送腾讯转化归因API请求失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 构建腾讯转化归因API请求体
     * @param imei IMEI设备标识
     * @param idfa IDFA设备标识
     * @param caid CAID设备标识
     * @param os 操作系统类型
     * @param dmpid 用于生成outer_action_id
     * @return JSON请求体
     */
    private JSONObject buildTencentRequestBody(String imei, String idfa, String caid, String os,
     String androididMd5, String oaid, String oaidMd5, String dmpid, String event) {
        JSONObject requestBody = new JSONObject();
        JSONArray actions = new JSONArray();
        JSONObject action = new JSONObject();

        // 设置外部行为ID（用于去重）
        action.put("outer_action_id", "outer_action_" + dmpid + "_" + System.currentTimeMillis());
        // 设置行为时间（使用当前时间）
        action.put("action_time", System.currentTimeMillis() / 1000);

        // 设置用户标识
        JSONObject userId = new JSONObject();

        // 根据操作系统类型处理设备标识，进行MD5加密
        String osLower = os.toLowerCase();

        if (osLower.contains("android")) {
            if (StringUtils.isNotBlank(imei)) {
                userId.put("hash_imei", md5Hash(imei));
            }
            if (StringUtils.isNotBlank(androididMd5)) {
                userId.put("hash_android_id", androididMd5);
            }
            if (StringUtils.isNotBlank(oaid)) {
                userId.put("oaid", oaid);
            }
            if (StringUtils.isNotBlank(oaidMd5)) {
                userId.put("hash_oaid", oaidMd5);
            }
        }else if (osLower.contains("ios")) {
            if (StringUtils.isNotBlank(idfa)) {
                userId.put("hash_idfa", md5Hash(idfa));
            }
            if (StringUtils.isNotBlank(caid)) {
               try {
                 // CAID需要进行URL编码
                 String encodedCaid = URLEncoder.encode(caid, "UTF-8");
                 JSONArray caidArray = JSONArray.parseArray(encodedCaid);
                 userId.put("caid", caidArray.getJSONObject(0).get("qaid")); // CAID通常已经是加密的
                 userId.put("caid_version", caidArray.getJSONObject(0).get("version")); // 默认版本号
               } catch (Exception e) {
                 e.printStackTrace();
               }
            }
        }

        action.put("user_id", userId);

        // 设置行为类型（默认为激活）
        String actionType = "ACTIVATE_APP";
        if("1".equals(event)){
            actionType = "REGISTER";
        }else if("2".equals(event)){
            actionType = "ACTIVATE_APP";
        }else if("3".equals(event) || "4".equals(event)){
            actionType = "START_APP";
        }
        action.put("action_type", actionType);

        // 设置行为参数
        JSONObject actionParam = new JSONObject();
        action.put("action_param", actionParam);

        actions.add(action);
        requestBody.put("actions", actions);

        return requestBody;
    }

    /**
     * 简单的MD5哈希方法
     * @param input 输入字符串
     * @return MD5哈希值
     */
    private static String md5Hash(String input) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] array = md.digest(input.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte b : array) {
                sb.append(Integer.toHexString((b & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString();
        } catch (java.security.NoSuchAlgorithmException e) {
            return input; // 如果MD5不可用，返回原值
        }
    }

}
